import 'package:flutter/material.dart';

class ContainerWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("容器组件"),
      ),
      body: PaddingWidget(),
    );
  }
}

/**
 * Flexible 和 Expanded
 * 子控件超过父控件宽高度限制会自动伸缩，当fit: FlexFit.tight时，不满父控件宽高会自动填充
 * flex,默认是1，子控件比例，子控件的伸缩时不与原来指定的宽高值相关，与flex比例关联
 * Expanded 是Flexible的子类,属性默认fit: FlexFit.tight
 */
class FlexibleWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        Flexible(
            child:
                Container(width: 550, height: 400, color: Colors.blueAccent)),
        Expanded(
            flex: 2,
            child:
                Container(width: 130, height: 300, color: Colors.yellowAccent)),
        Container(width: 30, height: 500, color: Colors.redAccent),
        Container(width: 20, height: 100, color: Colors.greenAccent),
      ],
    );
  }
}

class Container1Widget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      //可以指定大小，没有指定大小：没有子控件大小填充父控件，有子控件由子控件决定
      width: 200,
      height: 500,
      //有padding，margin,alignment属性
      padding: EdgeInsets.all(10),
      margin: EdgeInsets.all(16),
//      alignment: Alignment(0.3, 0.7),
      //color和decoration 不能同时出现，原因是color本身就是一个decoration
      decoration: BoxDecoration(
          color: Colors.amber,
          //border宽计算在widget宽里面
          border: Border.all(width: 2, color: Colors.blueAccent),
          //圆角，半径过大可以直接设置成圆
          borderRadius: BorderRadius.circular(20),
          //阴影,右下为正
          boxShadow: [
            BoxShadow(
                offset: Offset(10, 10),
                color: Colors.amber,
                spreadRadius: 5,
                blurRadius: 30),
            BoxShadow(
                offset: Offset(-10, 10),
                color: Colors.blueAccent,
                spreadRadius: 5, //在原先偏移的阴影上再加上距离
                blurRadius: 5)
          ]),
      transform: Matrix4.rotationZ(50),
      child: Icon(
        Icons.pets,
        color: Colors.white,
      ),
    );
  }
}

class PaddingWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Padding(
          //EdgeInsets.symmetric  垂直和水平方向
          //EdgeInsets.fromLTRB(left, top, right, bottom)  四个方向
          //EdgeInsets.only() 命名参数设置那个方向，没设置默认0
          padding: EdgeInsets.only(top: 10),
        ),
        Text(
          'hello world',
          style: TextStyle(fontSize: 20, backgroundColor: Colors.yellowAccent),
        ),
        Text(
          'hello world',
          style: TextStyle(fontSize: 20, backgroundColor: Colors.yellowAccent),
        ),
        Text(
          'hello world',
          style: TextStyle(fontSize: 20, backgroundColor: Colors.yellowAccent),
        ),
      ],
    );

//    return Padding(
//      padding: EdgeInsets.all(10),
//      child: Text(
//        'hello world',
//        style: TextStyle(fontSize: 20, backgroundColor: Colors.yellowAccent),
//      ),
//    );
  }
}

class AlignWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
//    return Container(
//      width: 200,
//      height: 300,
//      color: Colors.red,
//      child: Align(
//        alignment: Alignment(1, 1),
//        child: Icon(Icons.pets, size: 50),
//      ),
    return Align(
      widthFactor: 5, //宽缩放因子，以widget的宽为基准
      heightFactor: 10,
      alignment: Alignment(-1, -1),
      child: Icon(Icons.pets, size: 50),
    );
  }
}

/*
Align 组件可以调整子组件的位置，并且可以根据子组件的宽高来确定自身的的宽高

alignment : 需要一个AlignmentGeometry类型的值，表示子组件在父组件中的起始位置。
AlignmentGeometry 是一个抽象类，它有两个常用的子类：Alignment和 FractionalOffset
widthFactor和heightFactor是用于确定Align 组件本身宽高的属性；
它们是两个缩放因子，会分别乘以子元素的宽、高，最终的结果就是Align 组件的宽高。如果值为null，则组件的宽高将会占用尽可能多的空间。
 */

/*
使用Stack和Positioned这两个组件来配合实现绝对定位。Stack允许子组件堆叠，而Positioned用于根据Stack的四个角来确定子组件的位置。

Stack
alignment：此参数决定如何去对齐没有定位（没有使用Positioned）或部分定位的子组件。所谓部分定位，在这里特指没有在某一个轴上定位：
left、right为横轴，top、bottom为纵轴，只要包含某个轴上的一个定位属性就算在该轴上有定位。
textDirection：和Row、Wrap的textDirection功能一样，都用于确定alignment对齐的参考系，即：
textDirection的值为TextDirection.ltr，则alignment的start代表左，end代表右，即从左往右的顺序；textDirection的值为TextDirection.rtl，则alignment的start代表右，end代表左，即从右往左的顺序。
fit：此参数用于确定没有定位的子组件如何去适应Stack的大小。StackFit.loose表示使用子组件的大小，StackFit.expand表示扩伸到Stack的大小。
overflow：此属性决定如何显示超出Stack显示空间的子组件；值为Overflow.clip时，超出部分会被剪裁（隐藏），值为Overflow.visible 时则不会

Positioned
left、top 、right、 bottom分别代表离Stack左、上、右、底四边的距离。width和height用于指定需要定位元素的宽度和高度。
注意，Positioned的width、height 和其它地方的意义稍微有点区别，此处用于配合left、top 、right、 bottom来定位组件，举个例子，在水平方向时，你只能指定left、right、width三个属性中的两个，
如指定left和width后，right会自动算出(left+width)，如果同时指定三个属性则会报错，垂直方向同理
 */
class FrameWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //通过ConstrainedBox来确保Stack占满屏幕
    return ConstrainedBox(
      constraints: BoxConstraints.expand(),
      child: Stack(
        alignment: AlignmentDirectional.topCenter, //指定未定位或部分定位widget的对齐方式,没有定位方向的子控件以这个为准
        //fit: StackFit.expand,//未定位widget占满Stack整个空间
        children: <Widget>[
          Container(
            color: Colors.red,
            child: Text(
              "未定位",
              style: TextStyle(color: Colors.white),
            ),
          ),
          Positioned(
            child: Container(
              width: 80,
              height: 250,
              color: Colors.yellowAccent,
              child: Text(
                "右边定位",
                style: TextStyle(background: Paint()..color = Colors.green),
              ),
            ),
            right: -50,//反方向距离
          ),
          Positioned(
            child: Text("顶部定位",
                style: TextStyle(background: Paint()..color = Colors.green)),
            top: 200,
          ),
        ],
      ),
    );
  }
}

///把超出屏幕显示范围会自动折行的布局称为流式布局。
///wrap
///spacing：主轴方向子widget的间距
//runSpacing：纵轴方向的间距
//runAlignment：纵轴方向的对齐方式
class WrapWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Wrap(
      spacing: 8.0, // 主轴(水平)方向间距
      runSpacing: 4.0, // 纵轴（垂直）方向间距
      alignment: WrapAlignment.center, //沿主轴方向居中
      children: <Widget>[
        new Chip(
          avatar:
              new CircleAvatar(backgroundColor: Colors.blue, child: Text('A')),
          label: new Text('Hamilton'),
        ),
        new Chip(
          avatar:
              new CircleAvatar(backgroundColor: Colors.blue, child: Text('M')),
          label: new Text('Lafayette'),
        ),
        new Chip(
          avatar:
              new CircleAvatar(backgroundColor: Colors.blue, child: Text('H')),
          label: new Text('Mulligan'),
        ),
        new Chip(
          avatar:
              new CircleAvatar(backgroundColor: Colors.blue, child: Text('J')),
          label: new Text('Laurens'),
        ),
      ],
    );
  }
}

/// 线性布局嵌套
class LinearNestWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          //如果要让里面的Column占满外部Column，可以使用Expanded 组件：
//          Expanded(child:
          Container(
            color: Colors.red,
            child: Column(
              mainAxisSize: MainAxisSize.max, //无效，外层决定了
              children: <Widget>[
                Text("hello\nworld"),
              ],
            ),
          ),
//          )
        ],
      ),
    );
  }
}

class LinearWidget extends StatelessWidget {
  /*
  Row可以在水平方向排列其子widget
  textDirection：表示水平方向子组件的布局顺序(是从左往右还是从右往左)，默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右，而阿拉伯语是从右往左)。
mainAxisSize：表示Row在主轴(水平)方向占用的空间，默认是MainAxisSize.max，表示尽可能多的占用水平方向的空间，此时无论子widgets实际占用多少水平空间，
Row的宽度始终等于水平方向的最大宽度；而MainAxisSize.min表示尽可能少的占用水平空间，当子组件没有占满水平剩余空间，则Row的实际宽度等于所有子组件占用的的水平空间；

mainAxisAlignment：表示子组件在Row所占用的水平空间内对齐方式，如果mainAxisSize值为MainAxisSize.min，则此属性无意义，因为子组件的宽度等于Row的宽度。
只有当mainAxisSize的值为MainAxisSize.max时，此属性才有意义，MainAxisAlignment.start表示沿textDirection的初始方向对齐，
如textDirection取值为TextDirection.ltr时，则MainAxisAlignment.start表示左对齐，textDirection取值为TextDirection.rtl时表示从右对齐。
而MainAxisAlignment.end和MainAxisAlignment.start正好相反；MainAxisAlignment.center表示居中对齐。读者可以这么理解：textDirection是mainAxisAlignment的参考系。
verticalDirection：表示Row纵轴（垂直）的对齐方向，默认是VerticalDirection.down，表示从上到下。
crossAxisAlignment：表示子组件在纵轴方向的对齐方式，Row的高度等于子组件中最高的子元素高度，它的取值和MainAxisAlignment一样(包含start、end、 center三个值)，
不同的是crossAxisAlignment的参考系是verticalDirection，即verticalDirection值为VerticalDirection.down时crossAxisAlignment.start指顶部对齐，
verticalDirection值为VerticalDirection.up时，crossAxisAlignment.start指底部对齐；而crossAxisAlignment.end和crossAxisAlignment.start正好相反；
children ：子组件数组

Row和Column都只会在主轴方向占用尽可能大的空间，而纵轴的长度则取决于他们最大子元素的长度
   */
  @override
  Widget build(BuildContext context) {
    return Column(
      //水平可能默认居中，排除对子布局的影响
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(" hello world "),
            Text(" I am Jack "),
          ],
        ),
        Row(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(" hello world "),
            Text(" I am Jack "),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.end,
          textDirection: TextDirection.rtl,
          children: <Widget>[
            Text(" hello world "),
            Text(" I am Jack "),
          ],
        ),
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          verticalDirection: VerticalDirection.up,
          children: <Widget>[
            Text(
              " hello world ",
              style: TextStyle(fontSize: 30.0),
            ),
            Text(" I am Jack "),
          ],
        ),
      ],
    );
  }
}
